/*
 * Dcm_UDS0x24.c
 *
 *  Created on: 2018-8-9
 *      Author: tao.yu
 */
#include "UDS.h"


/****************************************************************
     UDS: ReadScalingDataByIdentifier (24 hex) service
 ***************************************************************/
#if (STD_ON == DCM_UDS_SERVICE0X24_ENABLED)

/************************/
#define  DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(Std_ReturnType, DCM_CODE)DspInternalUDS0x24_DidSessionCheck(
        uint8  DidInfoCfgIndex,
        P2VAR(Dcm_NegativeResponseCodeType, AUTOMATIC, AUTOMATIC)pNrc)
{
    uint8   Index = 0;
    boolean Flag = FALSE;
    P2CONST(Dcm_DspDidReadType, AUTOMATIC, DCM_APPL_CONST) pDspDidRead;
    Std_ReturnType   ret = E_OK;

    /***************************************
     * pDcmDspDidRead is NULL_PTR
     ***************************************/
    pDspDidRead  = Dcm_DspCfg.pDcmDspDidInfo[DidInfoCfgIndex].pDcmDspDidRead;
    if (NULL_PTR == pDspDidRead)
    {
        /*Dcm433:if the DcmDspDidRead of required Did is not configured,send NRC 0x31*/
        (*pNrc) = DCM_E_REQUESTOUTOFRANGE;
        ret = E_NOT_OK;
    }
    else
    {
        if (pDspDidRead->DcmDspDidReadSessionRefNum != 0u)
        {
			for (Index = 0;
					(Index < (pDspDidRead->DcmDspDidReadSessionRefNum))
							&& (FALSE == Flag);
					Index++)
			{
				if (Dcm_MkCtrl.Dcm_ActiveSes == pDspDidRead->pDcmDspDidReadSessionRow[Index])
				{
					Flag = TRUE;
				}
			}
			if (FALSE == Flag)
			{
				/*the reading processing is not supported in current session,send NRC 0x7F*/
				(*pNrc) = DCM_E_SERVICENOTSUPPORTEDINACTIVESESSION;
				ret = E_NOT_OK;
			}
        }
		else
		{
			ret = E_OK;
		}
    }
    return(ret);
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"

/***************************************/
#define  DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(Std_ReturnType, DCM_CODE)DspInternalUDS0x24_DidSecurityCheck(
        uint8  DidInfoCfgIndex,
        P2VAR(Dcm_NegativeResponseCodeType, AUTOMATIC, AUTOMATIC)pNrc)
{
    P2CONST(Dcm_DspDidReadType, AUTOMATIC, DCM_APPL_CONST) pDspDidRead;
    uint8    SecNum;
    uint8    Index = 0;
    Std_ReturnType   ret = E_OK;
    boolean  Flag = FALSE;



    /***************************************
     * pDcmDspDidRead is NULL_PTR
     ***************************************/
    pDspDidRead  = Dcm_DspCfg.pDcmDspDidInfo[DidInfoCfgIndex].pDcmDspDidRead;
    if (NULL_PTR == pDspDidRead)
    {
        /*Dcm433:if the DcmDspDidRead of required Did is not configured,send NRC 0x31*/
        (*pNrc) = DCM_E_REQUESTOUTOFRANGE;
        ret = E_NOT_OK;
    }
    else
    {
        SecNum = pDspDidRead->DcmDspDidReadSecurityLevelRefNum;
        if (SecNum != 0u)
        {
            for (Index = 0;
                    (Index < SecNum) && (FALSE == Flag);
                    Index++)
            {
                if (Dcm_MkCtrl.Dcm_ActiveSec
                        == pDspDidRead->pDcmDspDidReadSecurityLevelRow[Index])
                {
                    Flag = TRUE;
                }
            }
            if (FALSE == Flag)
            {
                /*Dcm435:the reading processing is not
                 *  supported in current security level,send NRC 0x33*/
               (*pNrc) = DCM_E_SECURITYACCESSDENIED;
                ret = E_NOT_OK;
            }
        }
        else
        {
            ret = E_OK;
        }
    }
    return(ret);
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"

/************************/
#define  DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(Std_ReturnType, DCM_CODE)DspInternalUDS0x24_DidCheck(uint16 receiveDid,
        P2VAR(uint16, AUTOMATIC, DCM_VAR_NOINIT)pDidCfgIndex)
{
    uint8     Index;
    boolean   Flag = FALSE;
    Std_ReturnType  ret = E_NOT_OK;

    /*SWS_Dcm_00438*/
    for (Index = 0;(Index < Dcm_DspCfg.DcmDspDidNum) && (FALSE == Flag); Index++)
    {
        /*single did check*/
        if ((receiveDid == Dcm_DspCfg.pDcmDspDid[Index].DcmDspDidId)
        &&(TRUE == Dcm_DspCfg.pDcmDspDid[Index].DcmDspDidUsed))
        {
            Flag = TRUE;
            (*pDidCfgIndex) = Index;
            ret = E_OK;
        }
    }

    return(ret);
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"


/***************************/
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(Std_ReturnType, DCM_CODE)Dcm_Uds0x24ServiceConditionCheck(
        uint8 ProtocolCtrlId,
        uint8 MsgCtrlId)
{
    Std_ReturnType ret = E_OK;

    /*************************************************/
#if(STD_ON == DCM_SESSION_FUNC_ENABLED)
    /*session check,check whether the current
     * session supports the request service*/
    ret = DsdInternal_SesCheck(ProtocolCtrlId,
            SID_READ_SCALING_DATA_BY_IDENTIFIER);
    if(E_NOT_OK == ret)
    {
        /****@req DCM-FUNR-073[DCM211]****/
        /*the current session does not support
         * the request service,send NRC = 0x7F*/
        (void)DsdInternal_SetNrc(ProtocolCtrlId,
                DCM_E_SERVICENOTSUPPORTEDINACTIVESESSION);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }
#endif

    /*************************************************/
#if(STD_ON == DCM_SECURITY_FUNC_ENABLED)
    /*security check,check whether the
     * current security supports the request service*/
    ret = DsdInternal_SecurityCheck(ProtocolCtrlId,
            SID_READ_SCALING_DATA_BY_IDENTIFIER);
    if(E_NOT_OK == ret)
    {
        /****@req DCM-FUNR-074[DCM217]****/
        /*the current security does not
         *  support the request service,send NRC = 0x33*/
        (void)DsdInternal_SetNrc(ProtocolCtrlId,
                DCM_E_SECURITYACCESSDENIED);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }
#endif
    /*length check*/
    if (DCM_UDS0X24_REQ_DATA_LENGTH
            != Dcm_MsgCtrl[MsgCtrlId].MsgContext.ReqDataLen)
    {
        /*the length of message is not correct,send NRC 0x13*/
        (void)DsdInternal_SetNrc(ProtocolCtrlId,
                DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }
    return ret;
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"


/*******************************/
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
FUNC(Std_ReturnType, DCM_CODE)Dcm_UDS0x24(
        Dcm_OpStatusType OpStatus,
        uint8  ProtocolCtrlId,
        P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_VAR) ErrorCode)
{
    uint8  MsgCtrlId = 0u;
    Std_ReturnType ret = E_OK;
    uint8  TxChannelCtrlIndex = 0u;
    uint8  TxChannelCfgIndex = 0u;
    uint16 Offset = 0u;
#if (STD_ON == DCM_DSP_DID_FUNC_ENABLED)
    uint16    DidCfgIndex;
    uint16    RecDid;
    uint8     DidInfoCfgIndex;
    uint8   SignalNum = 0;
    uint8 iloop = 0;
    P2CONST(Dcm_DspDidSignalType,TYPEDEF,DCM_CONST)pDcmDspDidSignal = NULL_PTR;
    uint16 DidSignalPos;
    uint16 ResOffset;
    uint16 DataSize = 0;
#endif

    /*************************************************/
    /*if the required protocol is configured,get the index of runtime datum*/
    MsgCtrlId =  Dcm_ProtocolCtrl[ProtocolCtrlId].MsgCtrlIndex;

    /*************************************************/
    ret = Dcm_Uds0x24ServiceConditionCheck(ProtocolCtrlId, MsgCtrlId);
    if(E_OK != ret)
    {
        return ret;
    }

    RecDid = (uint16)(((uint16)Dcm_MsgCtrl[MsgCtrlId].MsgContext.pReqData[1u]) << 8u) \
            |((uint16)(Dcm_MsgCtrl[MsgCtrlId].MsgContext.pReqData[2u]));

#if (STD_OFF == DCM_DSP_DID_FUNC_ENABLED)
    /*NRC 0x31:request out of range*/
    (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_REQUESTOUTOFRANGE);
    DsdInternal_ProcessingDone(ProtocolCtrlId);
    return E_NOT_OK;
#else
    /*find the required DID in configuration*/
    ret = DspInternalUDS0x24_DidCheck(RecDid, &DidCfgIndex);
    if (E_NOT_OK == ret)
    {
        /*if the required DID is not found in DcmDspDid,send NRC 0x31*/
        (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_REQUESTOUTOFRANGE);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }

    DidInfoCfgIndex = Dcm_DspCfg.pDcmDspDid[DidCfgIndex].DcmDspDidInfoIndex;

    /*check the current session*/
    #if(STD_ON == DCM_SESSION_FUNC_ENABLED)
    ret = DspInternalUDS0x24_DidSessionCheck(DidInfoCfgIndex,ErrorCode);
    if(E_NOT_OK == ret)
    {
        (void)DsdInternal_SetNrc(ProtocolCtrlId,*ErrorCode);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return  E_NOT_OK;
    }
    #endif

    /***************************************/
    /*check the current security level*/
    #if(STD_ON == DCM_SECURITY_FUNC_ENABLED)
    ret = DspInternalUDS0x24_DidSecurityCheck(DidInfoCfgIndex,ErrorCode);
    if(E_NOT_OK == ret)
    {
        (void)DsdInternal_SetNrc(ProtocolCtrlId,*ErrorCode);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return  E_NOT_OK;
    }
    #endif

    TxChannelCtrlIndex = Dcm_MsgCtrl[MsgCtrlId].Dcm_TxCtrlChannelIndex;
    TxChannelCfgIndex  = Dcm_ChannelCtrl[TxChannelCtrlIndex].Dcm_ChannelCfgIndex;
    Offset = (Dcm_DslCfg.pDcmChannelCfg)[TxChannelCfgIndex].offset;

    SignalNum = Dcm_DspCfg.pDcmDspDid[DidCfgIndex].DcmDspDidSignalNum;
    pDcmDspDidSignal = Dcm_DspCfg.pDcmDspDid[DidCfgIndex].pDcmDspDidSignal;
    ResOffset = Offset + 3u;
    for (iloop = 0; iloop < SignalNum; iloop++)
    {
        if (pDcmDspDidSignal != NULL_PTR)
        {
            DataSize = 0;
            DidSignalPos += ResOffset + ((pDcmDspDidSignal->DcmDspDidDataPos + 7u) >> 3u);
            if (pDcmDspDidSignal->pDcmDspDidData->DcmDspDataGetScalingInfoFnc != NULL_PTR)
            {
                ret = pDcmDspDidSignal->pDcmDspDidData->DcmDspDataGetScalingInfoFnc(
                        &Dcm_Channel[DidSignalPos],ErrorCode);
                if (ret != E_OK)
                {
                    (void)DsdInternal_SetNrc(ProtocolCtrlId,*ErrorCode);
                    DsdInternal_ProcessingDone(ProtocolCtrlId);
                    return  E_NOT_OK;
                }
            }
            if (DCM_UINT8_DYN == pDcmDspDidSignal->pDcmDspDidData->DcmDspDataType)
            {
                /*DidDataSize is dynamic*/
                if (NULL_PTR
                        == pDcmDspDidSignal->pDcmDspDidData->DcmDspDataReadDataLengthFnc)
                {
                    (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_CONDITIONSNOTCORRECT);
                    DsdInternal_ProcessingDone(ProtocolCtrlId);
                    return  E_NOT_OK;
                }
                else if((USE_DATA_SYNCH_FNC == pDcmDspDidSignal->pDcmDspDidData->DcmDspDataUsePort)
                 || (USE_DATA_SYNCH_CLIENT_SERVER == pDcmDspDidSignal->pDcmDspDidData->DcmDspDataUsePort))
                {
                    (void)pDcmDspDidSignal->pDcmDspDidData->DcmDspDataReadDataLengthFnc(
                            DCM_INVALID_UINT8,
                            &DataSize);
                }
                else if((USE_DATA_ASYNCH_FNC == pDcmDspDidSignal->pDcmDspDidData->DcmDspDataUsePort)
                   || (USE_DATA_ASYNCH_FNC_ERROR == pDcmDspDidSignal->pDcmDspDidData->DcmDspDataUsePort)
                   || (USE_DATA_ASYNCH_CLIENT_SERVER == pDcmDspDidSignal->pDcmDspDidData->DcmDspDataUsePort)
                   || (USE_DATA_ASYNCH_CLIENT_SERVER_ERROR == pDcmDspDidSignal->pDcmDspDidData->DcmDspDataUsePort))
                {
                    (void)pDcmDspDidSignal->pDcmDspDidData->DcmDspDataReadDataLengthFnc(
                            OpStatus,
                            &DataSize);
                }
                else
                {
                    /*idle*/
                }
            }
            else
            {
                /*DidDataSize is fixed*/
                if(0xffu != pDcmDspDidSignal->pDcmDspDidData->DcmDspDataInfoIndex)
                {
                    DataSize = Dcm_DspCfg.pDcmDspDataInfo[pDcmDspDidSignal->pDcmDspDidData->DcmDspDataInfoIndex].
                            DcmDspDataScalingInfoSize;
                }
                else
                {
                    DataSize = 0;
                }
            }
            ResOffset += DataSize;
        }
        pDcmDspDidSignal++;
    }

    /* check tx data length */
    if ((ResOffset - Offset)
            > (Dcm_DslCfg.pDcmChannelCfg[TxChannelCfgIndex].Dcm_DslBufferSize))
    {
        /*Pdu length is bigger than buffer size */
        (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_RESPONSETOOLONG);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }

    /**********************************************************
     * assemble positive response
     *********************************************************/
    /*the processing is successful,assemble positive response*/
    SchM_Enter_Dcm(Dcm_Channel);
    Dcm_Channel[Offset] = 0x64;             /*response SID*/
    Dcm_Channel[Offset + 1u] = (uint8)(RecDid >> 8u);
    Dcm_Channel[Offset + 2u] = (uint8)RecDid;
    SchM_Exit_Dcm(Dcm_Channel);
    SchM_Enter_Dcm(Dcm_MsgCtrl);
    Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResMaxDataLen = (Dcm_MsgLenType)ResOffset - Offset;
    Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResDataLen    = (Dcm_MsgLenType)ResOffset - Offset;
    Dcm_MsgCtrl[MsgCtrlId].MsgContext.pResData      = &Dcm_Channel[Offset];
    SchM_Exit_Dcm(Dcm_MsgCtrl);
    DsdInternal_ProcessingDone(ProtocolCtrlId);

    return ret;
#endif
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"

#endif
